package com.getpebble.android.framework.developer;

import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import com.getpebble.android.PebbleApplication;
import com.getpebble.android.bluetooth.protocol.ProtocolMessage;
import com.getpebble.android.common.core.trace.Analytics.RemoteAppBehavior;
import com.getpebble.android.common.core.trace.Trace;
import com.getpebble.android.common.model.FrameworkState;
import com.getpebble.android.common.model.FrameworkState.EventType;
import com.getpebble.android.common.model.FrameworkState.StateListener;
import com.getpebble.android.common.model.PblDevice;
import com.getpebble.android.framework.DeviceInterfaces.IDeviceMessageReceivedCallback;
import com.getpebble.android.framework.DeviceInterfaces.IDeviceMessageSender;
import com.getpebble.android.framework.DeviceInterfaces.IDeviceMessageSentCallback;
import com.getpebble.android.framework.comm.MessageRouter;
import com.getpebble.android.framework.endpoint.EndpointRequest;
import com.getpebble.android.framework.endpoint.EndpointRequest.EndpointAction;
import com.getpebble.android.framework.endpoint.EndpointRequest.EndpointArgumentKeys;
import com.getpebble.android.framework.endpoint.IEndpointMessageSender;
import com.getpebble.android.framework.endpoint.InstallAppEndpoint.AppInstallResult;
import com.getpebble.android.framework.protocol.EndpointId;
import com.getpebble.android.framework.protocol.outbound.PblOutboundByteMessage;
import com.getpebble.android.framework.protocol.outbound.PblOutboundMessage;
import com.getpebble.android.jskit.bridge.IJsLogSender;
import com.getpebble.android.jskit.bridge.JsDeveloperConnectionBridge;
import com.sun.mail.imap.protocol.ListInfo;
import com.sun.mail.smtp.SMTPMessage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;

public class DeveloperConnectionManager implements IDeviceMessageReceivedCallback, IDeviceMessageSentCallback, IEndpointMessageSender, IJsLogSender {
    public static final String TAG = DeveloperConnectionManager.class.getSimpleName();
    private static Handler sDeveloperConnectionHandler;
    private WeakReference<IConnection> mConnection;
    private WeakReference<Context> mContext;
    private IDeviceMessageSender mDeviceMessageSender;

    static /* synthetic */ class AnonymousClass2 {
        static final /* synthetic */ int[] $SwitchMap$com$getpebble$android$framework$developer$DeveloperConnectionManager$WebSocketCommand = new int[WebSocketCommand.values().length];

        static {
            try {
                $SwitchMap$com$getpebble$android$framework$developer$DeveloperConnectionManager$WebSocketCommand[WebSocketCommand.PEBBLE_PROTOCOL_PHONE_TO_WATCH.ordinal()] = 1;
            } catch (NoSuchFieldError e) {
            }
            try {
                $SwitchMap$com$getpebble$android$framework$developer$DeveloperConnectionManager$WebSocketCommand[WebSocketCommand.APP_INSTALL.ordinal()] = 2;
            } catch (NoSuchFieldError e2) {
            }
            try {
                $SwitchMap$com$getpebble$android$framework$developer$DeveloperConnectionManager$WebSocketCommand[WebSocketCommand.PHONE_INFO.ordinal()] = 3;
            } catch (NoSuchFieldError e3) {
            }
        }
    }

    public enum WebSocketCommand {
        PEBBLE_PROTOCOL_WATCH_TO_PHONE((byte) 0),
        PEBBLE_PROTOCOL_PHONE_TO_WATCH((byte) 1),
        PHONE_APP_LOG((byte) 2),
        PHONE_SERVER_LOG((byte) 3),
        APP_INSTALL((byte) 4),
        STATUS_CODE((byte) 5),
        PHONE_INFO((byte) 6),
        CONNECTION_STATUS((byte) 7),
        PROXY_CONNECTION_STATUS((byte) 8);
        
        private byte mCode;

        private WebSocketCommand(byte code) {
            this.mCode = code;
        }

        public byte getCode() {
            return this.mCode;
        }

        public static WebSocketCommand fromCode(byte code) {
            for (WebSocketCommand command : values()) {
                if (command.getCode() == code) {
                    return command;
                }
            }
            return null;
        }
    }

    public enum WebSocketStatus {
        SUCCESS(0),
        INSTALL_FAILED(1);
        
        private int mCode;

        private WebSocketStatus(int code) {
            this.mCode = code;
        }

        public int getCode() {
            return this.mCode;
        }
    }

    static {
        HandlerThread handlerThread = new HandlerThread("developerconnection");
        handlerThread.start();
        sDeveloperConnectionHandler = new Handler(handlerThread.getLooper());
    }

    static Handler getHandler() {
        return sDeveloperConnectionHandler;
    }

    public DeveloperConnectionManager(Context context, IConnection connection, IDeviceMessageSender messageSender) throws IllegalArgumentException {
        if (context == null) {
            throw new IllegalArgumentException("'context' cannot be null!");
        } else if (connection == null) {
            throw new IllegalArgumentException("'connection' cannot be null!");
        } else if (messageSender == null) {
            throw new IllegalArgumentException("'deviceMessageSender' cannot be null");
        } else {
            this.mContext = new WeakReference(context);
            this.mConnection = new WeakReference(connection);
            this.mDeviceMessageSender = messageSender;
            this.mDeviceMessageSender.registerBluetoothMessageCallback(this);
            this.mDeviceMessageSender.registerMessageSentCallback(this);
            JsDeveloperConnectionBridge.getInstance().setLogSender(this);
        }
    }

    public IConnection getConnection() {
        if (this.mConnection != null) {
            return (IConnection) this.mConnection.get();
        }
        return null;
    }

    public IDeviceMessageSender getDeviceMessageSender() {
        return this.mDeviceMessageSender;
    }

    public void handleMessageFromPblSdk(ByteBuffer buffer, FrameworkState frameworkState) {
        if (buffer.remaining() < 1) {
            Trace.error(TAG, "received websocket message shorter than a header");
            return;
        }
        byte commandCode = buffer.get();
        WebSocketCommand command = WebSocketCommand.fromCode(commandCode);
        Trace.debug(TAG, "Got command: " + command.name());
        switch (AnonymousClass2.$SwitchMap$com$getpebble$android$framework$developer$DeveloperConnectionManager$WebSocketCommand[command.ordinal()]) {
            case SMTPMessage.RETURN_FULL /*1*/:
                sendProtocolMessage(buffer);
                return;
            case SMTPMessage.RETURN_HDRS /*2*/:
                RemoteAppBehavior.logSdkAppInstalled();
                installApp(buffer, frameworkState);
                return;
            case ListInfo.INDETERMINATE /*3*/:
                sendPhoneInfo(buffer);
                return;
            default:
                Trace.error(TAG, "Unknown web socket command code: " + commandCode);
                return;
        }
    }

    private void sendProtocolMessage(ByteBuffer byteBuffer) {
        short length = byteBuffer.getShort();
        short endpointIdCode = byteBuffer.getShort();
        Trace.verbose(TAG, "Sending protocol message to endpoint: " + EndpointId.fromCode(endpointIdCode));
        if (byteBuffer.remaining() != length) {
            Trace.error(TAG, "Protocol message is invalid length.");
        } else {
            sendMessage(new PblOutboundByteMessage(EndpointId.fromCode(endpointIdCode), byteBuffer));
        }
    }

    private void installApp(ByteBuffer byteBuffer, FrameworkState frameworkState) {
        IOException e;
        Trace.verbose(TAG, "Installing app");
        byte[] bytes = new byte[byteBuffer.remaining()];
        byteBuffer.get(bytes);
        FileOutputStream outputStream = null;
        try {
            final File tempFile = File.createTempFile("websocket-install", ".pbw");
            FileOutputStream outputStream2 = new FileOutputStream(tempFile);
            try {
                outputStream2.write(bytes);
                outputStream2.close();
                Uri uri = Uri.fromFile(tempFile);
                Bundle args = new Bundle();
                args.putBoolean(EndpointArgumentKeys.AUTO_START_APP.toString(), true);
                args.putBoolean(EndpointArgumentKeys.VIBRATE.toString(), true);
                args.putBoolean(EndpointArgumentKeys.ALLOW_REINSTALL.toString(), true);
                args.putParcelable(EndpointArgumentKeys.URI.toString(), uri);
                EndpointRequest endpointRequest = new EndpointRequest(EndpointId.APP_INSTALL_MANAGER, EndpointAction.ADD_APP, args);
                PblDevice device = getDevice();
                if (device == null) {
                    Trace.info(TAG, "device is null; not installing app");
                    sendStatusCode(WebSocketStatus.INSTALL_FAILED);
                    outputStream = outputStream2;
                    return;
                }
                MessageRouter messageRouter = MessageRouter.getOrCreateRouter(getDeviceMessageSender(), device);
                final FrameworkState devFrameworkState = new FrameworkState(frameworkState);
                devFrameworkState.setStateListener(new StateListener() {
                    public void onStateChanged() {
                        if (devFrameworkState.getLastEvent() != null && devFrameworkState.getLastEvent().equals(EventType.APP_INSTALL_COMPLETE)) {
                            if (AppInstallResult.fromValue(devFrameworkState.getAppInstallResult()) == AppInstallResult.SUCCESS) {
                                DeveloperConnectionManager.this.sendStatusCode(WebSocketStatus.SUCCESS);
                            } else {
                                Trace.debug(DeveloperConnectionManager.TAG, "AppInstallResult was not success");
                                DeveloperConnectionManager.this.sendStatusCode(WebSocketStatus.INSTALL_FAILED);
                            }
                            tempFile.delete();
                        }
                    }
                });
                messageRouter.onRequest(endpointRequest, devFrameworkState);
                outputStream = outputStream2;
            } catch (IOException e2) {
                e = e2;
                outputStream = outputStream2;
                Trace.error(TAG, "unable to install app via websockets", e);
                if (outputStream != null) {
                    try {
                        outputStream.close();
                    } catch (IOException e1) {
                        Trace.error(TAG, "Unable to close output stream", e1);
                    }
                }
                sendStatusCode(WebSocketStatus.INSTALL_FAILED);
            }
        } catch (IOException e3) {
            e = e3;
            Trace.error(TAG, "unable to install app via websockets", e);
            if (outputStream != null) {
                outputStream.close();
            }
            sendStatusCode(WebSocketStatus.INSTALL_FAILED);
        }
    }

    private void sendStatusCode(WebSocketStatus status) {
        IConnection connection = getConnection();
        if (connection == null) {
            Trace.debug(TAG, "sendStatusCode: connection is null");
            return;
        }
        ByteBuffer msg = ByteBuffer.allocate(5);
        msg.put(WebSocketCommand.STATUS_CODE.getCode());
        msg.putInt(status.getCode());
        msg.flip();
        Trace.verbose(TAG, "Sending status code:  " + status);
        connection.sendMessageToAllConnections(msg);
    }

    private void sendPhoneInfo(ByteBuffer buffer) {
        if (buffer.get() != (byte) 0) {
            Trace.error(TAG, "invalid protocol byte received in phone info request");
            return;
        }
        String infoStr = "Android," + VERSION.RELEASE + "," + Build.MODEL;
        byte[] messageBytes = infoStr.getBytes();
        ByteBuffer msg = ByteBuffer.allocate(messageBytes.length + 1);
        msg.put(WebSocketCommand.PHONE_INFO.getCode());
        msg.put(messageBytes);
        msg.flip();
        Trace.debug(TAG, "Sending phone info string: " + infoStr);
        IConnection connection = getConnection();
        if (connection != null) {
            connection.sendMessageToAllConnections(msg);
        }
    }

    public void onDeviceMessageReceived(PblDevice device, ProtocolMessage message) {
        sendProtocolMessageToAllConnections(device, message, WebSocketCommand.PEBBLE_PROTOCOL_WATCH_TO_PHONE);
    }

    public void onDeviceMessageSent(PblDevice device, ProtocolMessage message) {
        sendProtocolMessageToAllConnections(device, message, WebSocketCommand.PEBBLE_PROTOCOL_PHONE_TO_WATCH);
    }

    private void sendProtocolMessageToAllConnections(PblDevice device, ProtocolMessage message, WebSocketCommand command) {
        if (device.equals(getDevice())) {
            ByteBuffer protocolBuffer = message.getDataBuffer();
            ByteBuffer socketBuffer = ByteBuffer.allocate(protocolBuffer.remaining() + 5);
            socketBuffer.put(command.getCode());
            socketBuffer.putShort((short) message.getDataSize());
            socketBuffer.putShort(message.getEndpointId());
            socketBuffer.put(protocolBuffer);
            socketBuffer.flip();
            IConnection connection = getConnection();
            if (connection != null) {
                connection.sendMessageToAllConnections(socketBuffer);
            }
        }
    }

    public void sendJsAppLogLine(String logMessage) {
        IConnection connection = getConnection();
        if (connection != null) {
            byte[] messageBytes = logMessage.getBytes();
            ByteBuffer msg = ByteBuffer.allocate(messageBytes.length + 1);
            msg.put(WebSocketCommand.PHONE_APP_LOG.getCode());
            msg.put(messageBytes);
            msg.flip();
            connection.sendMessageToAllConnections(msg);
        }
    }

    public void onMessageSendSuccess(PblDevice device) {
        Trace.verbose(TAG, "Message sent to " + device.getName());
    }

    public void onMessageSendFailed(PblDevice device) {
        Trace.error(TAG, "Failed to send message to: " + device.getName());
    }

    public boolean sendMessage(PblOutboundMessage message) {
        ProtocolMessage protocolMessage = ProtocolMessage.from(ByteBuffer.wrap(message.getBytes()));
        PblDevice device = getDevice();
        if (device != null) {
            return getDeviceMessageSender().sendMessage(device, protocolMessage);
        }
        Trace.info(TAG, "device is null; not sending message");
        return false;
    }

    public PblDevice getDevice() {
        return PebbleApplication.getConnectedDevice();
    }

    public void deInit() {
        Trace.debug(TAG, "deInit()");
        this.mDeviceMessageSender.unregisterBluetoothMessageCallback(this);
        this.mDeviceMessageSender.unregisterMessageSentCallback(this);
    }
}
